using System;
using System.Collections;
using Algorithms.Placement;

namespace Algorithms.Graph.Searching
{
	public interface ISearch
	{
		void Search(IVertex vertex);
	}

	public interface IGraphWorker
	{
		void Execute(IVertex vertex);
	}

	public abstract class SearchTemplate : ISearch
	{
		protected IPlacement placement;

		protected IGraphWorker worker;

		public void SetWorker(IGraphWorker worker)
		{
			this.worker = worker;
		}

		#region SearchAlgorithm Members

		public void Search(IVertex vertex)
		{
			while(! placement.IsEmpty())
			{
				if(vertex.Visited)
				{
					return;
				}

				worker.Execute(vertex);

				foreach(IVertex subVertex in vertex.GetLinkedVertices())
				{
					this.placement.Add(subVertex);
				}
			}
		}

		#endregion
	}

	public class DepthFirstSearch : SearchTemplate
	{
		public DepthFirstSearch()
		{
			base.placement = new StackPlacement();
		}
	}

	public class BoardFirstSearch : SearchTemplate
	{
		public BoardFirstSearch()
		{
			base.placement = new QueuePlacement();
		}
	}

	public class Printer : IGraphWorker
	{
		public void Execute(IVertex vertex)
		{
			Console.WriteLine(vertex.Name);
		}
	}
}